package com.mrchip;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * @author MrChip
 */
public class HttpAccess implements Runnable {
    private static HttpAccess mInstance = null;
    private String mHost;
    private String mURL;
    private String mBody;
    private String mMethod;
    private Map<String, HttpAccessListener> mResponsers;

    public static synchronized HttpAccess getInstance() {
        if (mInstance == null) {
            mInstance = new HttpAccess();
        }
        return mInstance;
    }



    public void setHost(String host) {
        mHost = host;
    }

    private HttpAccess() {
        mResponsers = new HashMap<String, HttpAccessListener>();
    }

    /**
     * @param key Parameter must be compatible with the http methods apis.
     * @param listener The actor for response.
     */
    public void setResponser(String key, HttpAccessListener listener) {
        if (!mResponsers.containsKey(key)) {
            mResponsers.put(key, listener);
        }
    }

    public HttpURLConnection createConnection(String url) {
        HttpURLConnection httpURLConnection = null;
        try {
            httpURLConnection = (HttpURLConnection) (new URL(url).openConnection());
            httpURLConnection.setConnectTimeout(10 * 1000);
            httpURLConnection.setReadTimeout(10 * 1000);
            httpURLConnection.setRequestProperty("charset", "utf-8");
            httpURLConnection.setRequestProperty("Content-Type", "text/plain");
            httpURLConnection.setRequestProperty("Accept", "*/*");
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return httpURLConnection;
    }

    public void login(String user, String password) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("http://");
        stringBuilder.append(mHost);
        stringBuilder.append("/User/Login/");
        stringBuilder.append(user);
        mURL = stringBuilder.toString();
        mBody = password;
        mMethod = "Login";
        run();
    }

    public void register(String user, String password) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("http://");
        stringBuilder.append(mHost);
        stringBuilder.append("/User/Register/");
        stringBuilder.append(user);
        mURL = stringBuilder.toString();
        mBody = password;
        mMethod = "Register";
        run();
    }

    public void attend(String uuid) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("http://");
        stringBuilder.append(mHost);
        stringBuilder.append("/Attend/On/");
        stringBuilder.append(uuid);
        mURL = stringBuilder.toString();
        mBody = "";
        mMethod = "Attend";
        run();
    }

    public void leave(String uuid) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("http://");
        stringBuilder.append(mHost);
        stringBuilder.append("/Attend/Off/");
        stringBuilder.append(uuid);
        mURL = stringBuilder.toString();
        mBody = "";
        mMethod = "Leave";
        run();
    }

    public void query(String uuid) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("http://");
        stringBuilder.append(mHost);
        stringBuilder.append("/Attend/QUERY/");
        stringBuilder.append(uuid);
        mURL = stringBuilder.toString();
        mBody = "";
        mMethod = "Query";
        run();
    }



    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see //Thread#run()
     */
    @Override
    public synchronized void  run() {
        try {
            HttpURLConnection httpURLConnection = createConnection(mURL);
            OutputStream outputStream = new
                    BufferedOutputStream(httpURLConnection.getOutputStream());

            byte[] body = mBody.getBytes("utf-8");
            outputStream.write(body, 0, body.length);
            outputStream.flush();
            outputStream.close();
            InputStream inputStream = httpURLConnection.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line = null;
            StringBuilder stringBuilder = new StringBuilder();
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line + "\n");
            }
            String reponse = stringBuilder.toString();
            if (mResponsers.containsKey(mMethod)) {
                mResponsers.get(mMethod).getHttpData(reponse);
            }
//            System.out.println(reponse);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}